<?php

/**
 * 下划线转换驼峰
 * @param string $url
 * @return string
 */
function url2class(string $url): string
{

    return join(array_map(function ($v) {
        return ucfirst($v);
    }, explode('_', $url)));
}

/**
 * 驼峰转下划线
 * @param string $value
 * @param string $delimiter
 * @return string
 */
function class2url(string $value, string $delimiter = null)
{
    if (is_null($delimiter)) {
        $delimiter = '_';
    }
    if (!ctype_lower($value)) {
        $value = preg_replace('/\s+/u', '', $value);

        $value = strtolower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
    }

    return $value;
}

function coco_sleep(float $sec)
{
    usleep(intval(floatval($sec) * 1000000));
}

function coco_microtime()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}

/**
 * 获取依赖
 * @param ReflectionMethod $method
 * @return array
 * @throws ReflectionException
 * @throws \coco\Exception
 */
function getMethodParams(ReflectionMethod $method, array $arguments = []): array
{
    $params = $method->getParameters();
    $args = [];
    foreach ($params as $param) {
        if (!$param->getType()->isBuiltin()) {
            //外部绑定
            $ref_class = new ReflectionClass((string)$param->getType());
            if (in_array(\coco\traits\Singleton::class, class_uses($ref_class->name))) {
                $instance = call_user_func([(string)$param->getType(), 'getInstance']);
            } //不是单例检查是否在注册树上
            elseif (\coco\Tree::getInstance()->has((string)$param->getType())) {
                $instance = \coco\Tree::getInstance()->get((string)$param->getType());
            } else {
                //尝试new
                $constructor = $ref_class->getConstructor();
                if ($constructor) {
                    //如果存在构造方法
                    $argvs = getMethodParams($constructor);
                    $instance = $ref_class->newInstanceArgs($argvs);
                } else {
                    $instance = $ref_class->newInstance();
                }
            }
            $args[] = $instance;
        } else {
            //如果没有默认值 报错
            if (array_key_exists($param->name, $arguments)) {
                $args[] = $arguments[$param->name];
            } elseif (!$param->isDefaultValueAvailable()) {
                throw new \coco\Exception("方法没有默认值:" . $method->class . "::" . $method->name . "->" . $param->name);
            } else {
                $args[] = $param->getDefaultValue();
            }
        }
    }
    return $args;
}

function class_basename($class)
{
    return basename(str_replace('\\', '/', $class));
}

/**
 * 获取客户端IP地址
 * @return string
 */
function get_client_ip()
{
    static $ip;
    if ($ip) {
        return $ip;
    }
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        return is_ip($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : $ip;
    } elseif (!empty($_SERVER['HTTP_X_REAL_FORWARDED_FOR'])) {
        return is_ip($_SERVER['HTTP_X_REAL_FORWARDED_FOR']) ? $_SERVER['HTTP_X_REAL_FORWARDED_FOR'] : $ip;
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        return is_ip($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $ip;
    } else {
        return is_ip($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : $ip;
    }
    return $ip;
}
function is_ip($str)
{
    $ip = explode('.', $str);
    for ($i = 0; $i < count($ip); $i++) {
        if ($ip[$i] > 255) {
            return false;
        }
    }
    return preg_match('/^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$/', $str);
}
